

function log (x, y='World') {
    console.log(x, y)
}

log(12)
log(12, 'hahah')



// rest 参数，代替了原来的 arguments 对象

function add(...values) {
    let res = 0
    values.forEach(v=>{
        res += v
    })
    console.log(res, values)
    return res
}

add(2, 3, 4)

console.log(add.name)


const abc = 'function'
var abd  = 'kkkk'

// this 和 匿名箭头函数
function this1() {
    console.log(this)
}

let this2 = () => {
    console.log(this)
}

this1()
this2()
/**
<ref *1> Object [global] {
  global: [Circular *1],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
  },
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Function (anonymous)]
  }
}
{}
 */

console.log(this1)
console.log(this2)

/**
 * 箭头函数的this说明：
 * 
 * 函数体内的this对象，就是定义时所在的对象，而不是使用时所在的对象。
 *  this2 中，this是在当前文件定义的
 * 不可以当作构造函数，也就是说，不可以使用new命令，否则会抛出一个错误。
 * 不可以使用arguments对象，该对象在函数体内不存在。如果要用，可以用 rest 参数代替。
 * 不可以使用yield命令，因此箭头函数不能用作 Generator 函数。
 */


function foo() {
    setTimeout(() => {
      console.log('id:', this.id)
    }, 1000)

    setTimeout(function(){
        console.log('id', this.id)
    }, 1000)

}
  
var id = 21;

foo.call({ id: 42 });

// 尾调用



/**
 * call()、apply()、bind() 都是用来重定义 this 这个对象的！
 * apply call的区别：第二个参数的类型
 */

function show(obj) {
    console.log(obj)
}

const param = ['hello', 'world']
show.apply(null, param)
show.call(null, ...param)
show.bind(null, ...param)()

const maxNum = Math.max.apply(null, [1, 21, 8])
console.log(maxNum)

const arr1 = [0, 1, 2]
const arr2 = [3, 4, 5]
// Array.push() 支持一次添加多个参数，但不能直接添加另一个数组
Array.prototype.push.apply(arr1, arr2)
console.log(arr1)
